home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / ds5000.md / netDFXmit.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  30KB  |  1,041 lines

  1. /* 
  2.  * netDFXmit.c --
  3.  *
  4.  *    Routines to transmit packets on the DEC 700 FDDI controller.
  5.  *
  6.  * Copyright 1992 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/ds5000.md/netDFXmit.c,v 1.2 92/06/08 22:46:03 jhh Exp $";
  19. #endif
  20.  
  21. #include <sprite.h>
  22. #include <sys.h>
  23. #include <netDFInt.h>
  24. #include <vm.h>
  25. #include <vmMach.h>
  26. #include <list.h>
  27. #include <sync.h>
  28. #include <machMon.h>
  29.  
  30. #include <dbg.h>
  31.  
  32. /*
  33.  * Macros to step RMC XMT ring pointers.
  34.  */
  35. #define    NEXT_RMC_SEND(p) ( (((p)+1) > statePtr->rmcXmtLastDescPtr) ? \
  36.                 statePtr->rmcXmtFirstDescPtr : \
  37.                 ((p)+1))
  38. #define    PREV_RMC_SEND(p) ( (((p)-1) < statePtr->rmcXmtFirstDescPtr) ? \
  39.                 statePtr->rmcXmtLastDescPtr : \
  40.                 ((p)-1))
  41. /*
  42.  * Macros to step SMT XMT ring pointers.
  43.  */
  44. #define    NEXT_SMT_SEND(p) ( (((p)+1) > statePtr->smtXmtLastDescPtr) ? \
  45.                 statePtr->smtXmtFirstDescPtr : \
  46.                 ((p)+1))
  47.  
  48. static ReturnStatus OutputPacket _ARGS_((Net_FDDHdr *fddiHdrPtr, 
  49.                      Net_ScatterGather *scatterGatherPtr, 
  50.                      int scatterGatherLength, 
  51.                      NetDFState *statePtr));
  52.  
  53. /*
  54.  * To access the buffer corresponding to the RMC XMT descriptor
  55.  */
  56. #define RmcXmtBufFromDesc(statePtr, descPtr) \
  57.   (statePtr->rmcXmtFirstBufPtr + \
  58.    (unsigned long)(descPtr - statePtr->rmcXmtFirstDescPtr))
  59.  
  60.  
  61. /*
  62.  *----------------------------------------------------------------------
  63.  *
  64.  * NetDFBcopy --
  65.  *
  66.  *      Just like bcopy(), except that all data is transfered in words
  67.  *      on word-aligned boundaries.  The adapter requires that this
  68.  *      be so.
  69.  *
  70.  * Results:
  71.  *    None.
  72.  *
  73.  * Side effects:
  74.  *    None.
  75.  *
  76.  *----------------------------------------------------------------------
  77.  */
  78. void
  79. NetDFBcopy(startPtr, destPtr, numBytes)
  80.     unsigned char *startPtr;
  81.     unsigned char *destPtr;
  82.     unsigned long numBytes;
  83. {
  84.     register unsigned char *bytePtr, *toPtr, *fromPtr;
  85.     register unsigned long *div;
  86.     register unsigned long mod, length, aligned;
  87.     register unsigned long n;
  88.     unsigned long          value;
  89.  
  90.     /*
  91.      * One of the most annoying things about this adapter is that,
  92.      * although you can read bytes, you can't write bytes that
  93.      * are not word-aligned.  This is a pain, because we can't just
  94.      * flat out use bcopy()...we have to massage the beginnings and
  95.      * ends of the buffers so that we use bcopy only on an integral
  96.      * number of words.
  97.      */
  98.     fromPtr = startPtr;
  99.     toPtr = destPtr;
  100.     length = numBytes;
  101.  
  102.     if (length == 0) {
  103.     return;
  104.     }
  105.  
  106.     mod = (unsigned long)toPtr % sizeof(unsigned long);
  107.     div = (unsigned long *)(((unsigned long)toPtr >> 2) << 2);
  108.  
  109.     /*
  110.      * Write bytes to the destination array until the pointer
  111.      * is word-aligned.
  112.      */
  113.     value = *div;
  114.     bytePtr = (unsigned char *)&value;
  115.     switch((int)mod) {
  116.     case 1:
  117.     bytePtr[1] = fromPtr[0];
  118.     fromPtr++;
  119.     case 2:
  120.     bytePtr[2] = fromPtr[0];
  121.     fromPtr++;
  122.     case 3:
  123.     bytePtr[3] = fromPtr[0];
  124.     fromPtr++;
  125.     *div = value;
  126.     length -= (4 - mod);
  127.     toPtr += (4 - mod);
  128.     default:
  129.     break;
  130.     }
  131.  
  132.     aligned = (length >> 2) << 2;
  133.     /*
  134.      * We are really hosed if the source buffer is not word aligned
  135.      * after we align the dest buffer.  The adapter write addressing
  136.      * really stinks.  Luckily this appears to be a rare occurance.
  137.      */
  138.     mod = (unsigned long)fromPtr % sizeof(unsigned long);
  139.     if (mod) {
  140.     n = aligned;
  141.     div = (unsigned long *)toPtr;
  142.     while (n > 0) {
  143.         value = *div;
  144.         bytePtr = (unsigned char *)&value;
  145.         bytePtr[0] = fromPtr[0];
  146.         bytePtr[1] = fromPtr[1];
  147.         bytePtr[2] = fromPtr[2];
  148.         bytePtr[3] = fromPtr[3];
  149.         *div = value;
  150.         div++;
  151.         fromPtr += 4;
  152.         n -= 4;
  153.     }
  154.     toPtr += aligned;
  155.     } else { 
  156.     /*
  157.      * Only bcopy() an integral number of words. 
  158.      */
  159.     if (aligned != 0) {
  160.         bcopy(fromPtr, toPtr, aligned);
  161.         toPtr += aligned;
  162.         fromPtr += aligned;
  163.     }
  164.     } 
  165.  
  166.     /*
  167.      * finish up the tail end of the buffers
  168.      */
  169.     if (aligned != length) {
  170.     mod = length - aligned;
  171.     div = (unsigned long *)toPtr;
  172.     
  173.     value = *div;
  174.     bytePtr = (unsigned char *)&value;
  175.     switch((int)mod) {
  176.     case 3:
  177.         bytePtr[2] = fromPtr[2];
  178.     case 2:
  179.         bytePtr[1] = fromPtr[1];
  180.     case 1:
  181.         bytePtr[0] = fromPtr[0];
  182.         *div = value;
  183.     default:
  184.         break;
  185.     }
  186.     }
  187.  
  188.     /*
  189.      * Extra anal debugging.
  190.      */
  191.     if (netDFDebug == NET_DF_DEBUG_ON) {
  192.     for (n = 0; n < numBytes; n++) {
  193.         if (startPtr[n] != destPtr[n]) {
  194.         printf("DEC FDDI: NetDFBcopy failed!\n");
  195.         DBG_CALL;
  196.         Mach_EmptyWriteBuffer();
  197.         Mach_EmptyWriteBuffer();
  198.         Mach_EmptyWriteBuffer();
  199.         Mach_EmptyWriteBuffer();
  200.         return;
  201.         }
  202.     }
  203.     }
  204. }
  205.  
  206. /*
  207.  *----------------------------------------------------------------------
  208.  *
  209.  * OutputXmtElement --
  210.  *
  211.  *      Transmit the given packet that was waiting on the transmit
  212.  *      queue.  The element is removed from the queue.
  213.  *
  214.  * Results:
  215.  *    SUCCESS if the packet was successfully transmitted; FAILURE
  216.  *      otherwise.
  217.  *
  218.  * Side effects:
  219.  *    A packet is output.
  220.  *
  221.  *----------------------------------------------------------------------
  222.  */
  223. OutputXmtElement(statePtr, xmtElementPtr)
  224.     register NetDFState      *statePtr;
  225.     register NetDFXmtElement *xmtElementPtr;
  226. {
  227.     int status;
  228.     
  229.     switch(xmtElementPtr->xmtType) { 
  230.     case NET_DF_XMT_HOST: 
  231.     DFprintf("DEC FDDI: Outputting LLC packet.\n"); 
  232.     status = OutputPacket(xmtElementPtr->fddiHdrPtr, 
  233.                 xmtElementPtr->scatterGatherPtr, 
  234.                 xmtElementPtr->scatterGatherLength,  
  235.                 statePtr); 
  236.     DFprintf("DEC FDDI: Finished outputting LLC packet.\n"); 
  237.     break; 
  238.     case NET_DF_XMT_SMT: 
  239.     status = NetDFOutputSmtPacket(statePtr,  
  240.                       xmtElementPtr->smtDescPtr); 
  241.     break; 
  242.     default: 
  243.     printf("DEC FDDI: Unknown XMT element packet type.\n"); 
  244.     status = FAILURE; 
  245.     break; 
  246.     } 
  247.     List_Move((List_Links *) xmtElementPtr, 
  248.           LIST_ATREAR(statePtr->xmitFreeList)); 
  249.     return status;
  250. }
  251.  
  252. /*
  253.  *----------------------------------------------------------------------
  254.  *
  255.  * CastOffPacket --
  256.  *
  257.  *      Given pointers to the first and last RMC XMT descriptors,
  258.  *      transfer ownerships of those descriptors to the adapter
  259.  *      and tell it to start transmitting those descriptors.
  260.  *
  261.  * Results:
  262.  *    FAILURE if something went wrong.
  263.  *
  264.  * Side effects:
  265.  *    The adapter will start transmitting.
  266.  *
  267.  *----------------------------------------------------------------------
  268.  */
  269. static void
  270. CastOffPacket(statePtr, firstDescPtr, lastDescPtr)
  271.     register NetDFState               *statePtr;
  272.     register volatile NetDFRmcXmtDesc *firstDescPtr;
  273.     register volatile NetDFRmcXmtDesc *lastDescPtr;
  274. {
  275.     register volatile NetDFRmcXmtDesc *descPtr;
  276.     unsigned long                     own;
  277.  
  278.     descPtr = lastDescPtr;
  279.     /*
  280.      * Give the buffers used to the adapter.  Avoid race conditions
  281.      * by starting with the last RMC XMT buffer and ending with
  282.      * the first.
  283.      */
  284.     while (TRUE) {
  285.     descPtr->own = NET_DF_RMC_ADAPTER_OWN;
  286.     if (descPtr == firstDescPtr) {
  287.         break;
  288.     }
  289.     descPtr = PREV_RMC_SEND(descPtr);
  290.     }
  291.     /*
  292.      * Due to pipelineing in the adapter, we must read the own bit back
  293.      * on the first descriptor to ensure that it was placed there.
  294.      */
  295.     own = descPtr->own;
  296.     if ((own & NET_DF_RMC_OWN) == NET_DF_RMC_HOST_OWN) {
  297.     MAKE_NOTE("host owns RMC XMT descriptor!");
  298.     }
  299.     /*
  300.      * Give the adapter a little kick.
  301.      */
  302.     *(statePtr->regCtrlA) |= NET_DF_CTRLA_XMT_POLL_DEMAND;
  303.     Mach_EmptyWriteBuffer();
  304.     statePtr->stats.packetsQueued++;
  305.     return;
  306. }
  307.  
  308. /*
  309.  *----------------------------------------------------------------------
  310.  *
  311.  * NetDFXmitInit --
  312.  *
  313.  *    Initialize the transmission queue structures.  This includes setting
  314.  *    up the transmission ring buffers.
  315.  *
  316.  * Results:
  317.  *    None.
  318.  *
  319.  * Side effects:
  320.  *    The transmission ring is initialized.
  321.  *
  322.  *----------------------------------------------------------------------
  323.  */
  324. void
  325. NetDFXmitInit(statePtr)
  326.     register NetDFState        *statePtr;     /* State of the interface. */
  327. {
  328.     if (!statePtr->xmitMemAllocated) {
  329.     /*
  330.      * SMT XMT ring
  331.      */
  332.     statePtr->smtXmtFirstDescPtr = (NetDFSmtXmtDesc *)
  333.         (statePtr->initComPtr->smtXmtBase + statePtr->slotAddr);
  334.     /*
  335.      * RMC XMT ring
  336.      */
  337.     statePtr->rmcXmtFirstDescPtr = (NetDFRmcXmtDesc *)
  338.         (statePtr->initComPtr->rmcXmtBase + statePtr->slotAddr);
  339.     statePtr->xmitMemAllocated = TRUE;
  340.     }
  341.     /*
  342.      * Reset the SMT and RMC XMT ring pointers.
  343.      */
  344.     statePtr->smtXmtNextDescPtr = statePtr->smtXmtFirstDescPtr;
  345.     statePtr->smtXmtLastDescPtr = statePtr->smtXmtFirstDescPtr +
  346.     (statePtr->initComPtr->smtXmtEntries - 1);
  347.     statePtr->rmcXmtNextDescPtr = statePtr->rmcXmtFirstDescPtr;
  348.     statePtr->rmcXmtLastDescPtr = statePtr->rmcXmtFirstDescPtr +
  349.     (statePtr->initComPtr->rmcXmtEntries - 1);
  350.  
  351.     statePtr->xmitMemInitialized = TRUE;
  352.  
  353.     return;
  354. }
  355.  
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * NetDFOutputSmtPacket --
  360.  *
  361.  *      Transfer an SMT packet from the SMT XMT ring and place it
  362.  *      onto the RMC XMT ring.  
  363.  *
  364.  * Results:
  365.  *    FAILURE if something went wrong.
  366.  *
  367.  * Side effects:
  368.  *    Transmit ring is modified to contain the SMT packet.
  369.  *
  370.  *----------------------------------------------------------------------
  371.  */
  372. ReturnStatus
  373. NetDFOutputSmtPacket(statePtr, smtDescPtr)
  374.     register NetDFState               *statePtr;
  375.     register volatile NetDFSmtXmtDesc *smtDescPtr;
  376. {
  377.     register volatile NetDFRmcXmtDesc *descPtr;
  378.     register volatile NetDFRmcXmtBuf  *rmcBufPtr;
  379.     register unsigned char            *smtBufPtr;
  380.     register int                      length;
  381.  
  382.     descPtr = statePtr->rmcXmtNextDescPtr;
  383.  
  384.     /*
  385.      * Do some sanity checks. Why the polarity of the own bits on the
  386.      * two buffers are different, I don't know.
  387.      */
  388.     if ((descPtr->own & NET_DF_RMC_OWN) == NET_DF_RMC_ADAPTER_OWN) {
  389.     printf("DEC FDDI: RMC transmit buffer owned by adapter in SMT XMT.\n");
  390.     return (FAILURE);
  391.     }
  392.     if ((smtDescPtr->own & NET_DF_OWN) == NET_DF_ADAPTER_OWN) {
  393.     printf("DEC FDDI: SMT transmit buffer owned by adapter in SMT XMT.\n");
  394.     return (FAILURE);
  395.     }
  396.  
  397.     statePtr->transmitting = TRUE;
  398.     statePtr->hostTransmit = FALSE;
  399.     statePtr->curScatGathPtr = (Net_ScatterGather *)NIL;
  400.     statePtr->curSmtXmtDescPtr = smtDescPtr;
  401.     rmcBufPtr = RmcXmtBufFromDesc(statePtr, descPtr);
  402.     smtBufPtr = (unsigned char *)
  403.     (statePtr->slotAddr + (unsigned long)(smtDescPtr->bufAddr));
  404.     length = smtDescPtr->pbc;
  405.  
  406.     /*
  407.      * Transfer the data from the SMT XMT ring to the RMC XMT ring.
  408.      */
  409.     descPtr->rmcXmtDesc = NET_DF_RMC_XMT_FIRST_PAGE | (unsigned long)length;
  410.     while (length > 0) {
  411.     if (length < NET_DF_RMC_XMT_BUF_SIZE) {
  412.         NetDFBcopy(smtBufPtr, rmcBufPtr, length);
  413.         break;
  414.     } else {
  415.         NetDFBcopy(smtBufPtr, rmcBufPtr, NET_DF_RMC_XMT_BUF_SIZE);
  416.         length -= NET_DF_RMC_XMT_BUF_SIZE;
  417.         smtBufPtr += NET_DF_RMC_XMT_BUF_SIZE;
  418.         descPtr = NEXT_RMC_SEND(descPtr);
  419.         descPtr->rmcXmtDesc = NET_DF_RMC_XMT_MIDDLE_PAGE;
  420.         rmcBufPtr = RmcXmtBufFromDesc(statePtr, descPtr);
  421.     }
  422.     }
  423.     descPtr->rmcXmtDesc |= NET_DF_RMC_XMT_LAST_PAGE;
  424.  
  425.     MAKE_NOTE("begin transmitting SMT packet.");
  426.     CastOffPacket(statePtr, statePtr->rmcXmtNextDescPtr, descPtr);
  427.     return(SUCCESS);
  428. }
  429.  
  430. /*
  431.  *----------------------------------------------------------------------
  432.  *
  433.  * OutputPacket --
  434.  *
  435.  *    Assemble and output the packet in the given scatter/gather element.
  436.  *    The FDDI header contains the address of the destination host
  437.  *    and the higher level protocol type already.
  438.  *
  439.  * Results:
  440.  *    FAILURE if something went wrong.
  441.  *
  442.  * Side effects:
  443.  *    Transmit command list is modified to contain the packet.
  444.  *
  445.  *----------------------------------------------------------------------
  446.  */
  447. static ReturnStatus
  448. OutputPacket(fddiHdrPtr, scatterGatherPtr, scatterGatherLength, statePtr)
  449.     Net_FDDIHdr               *fddiHdrPtr;       /* FDDI header of packet */
  450.     register Net_ScatterGather *scatterGatherPtr; /* Data portion of packet */
  451.     int                   scatterGatherLength; /* Length of data portion 
  452.                              * gather array. */
  453.     register NetDFState           *statePtr;        /* The interface state. */
  454. {
  455.     register volatile NetDFRmcXmtDesc    *descPtr;
  456.     register volatile unsigned char    *descBufPtr;
  457.     register Address            bufPtr;
  458.     register int            bufCount;
  459.     register int            length;
  460.     register int                        remaining;
  461.     int                    totalLength;
  462.     int                    i, n, l;
  463.  
  464.     descPtr = statePtr->rmcXmtNextDescPtr;
  465.     /*
  466.      * Do some sanity checks.
  467.      */
  468.     if ((descPtr->own & NET_DF_RMC_OWN) == NET_DF_RMC_ADAPTER_OWN) {
  469.     printf("DEC FDDI: Transmit buffer owned by adapter.\n");
  470.     return (FAILURE);
  471.     }
  472.  
  473.     statePtr->transmitting = TRUE;
  474.     statePtr->hostTransmit = TRUE;
  475.     statePtr->curScatGathPtr = scatterGatherPtr;
  476.     /*
  477.      * Total up the size of the packet.  Do a sanity check to make sure
  478.      * that the packet is not too large, and then make sure that we 
  479.      * own enough RMC XMT descriptors to dump the packet into.
  480.      */
  481.     totalLength = NET_DF_RMC_XMT_BUF_HDR_SIZE;
  482.     for (i = 0; i < scatterGatherLength; i++) {
  483.     totalLength += scatterGatherPtr[i].length;
  484.     } 
  485.     if (totalLength > NET_DF_MAX_PACKET_SIZE) {
  486.     printf("DEC FDDI: OutputPacket: packet too large (%d)\n", totalLength);
  487.     return FAILURE;
  488.     }
  489.     i = (totalLength / NET_DF_RMC_XMT_BUF_SIZE);
  490.     n = statePtr->rmcXmtLastDescPtr - statePtr->rmcXmtFirstDescPtr;
  491.     l = descPtr - statePtr->rmcXmtFirstDescPtr;
  492.     descPtr = statePtr->rmcXmtFirstDescPtr + ((i + l) % (n + 1));
  493.     if ((descPtr->own & NET_DF_RMC_OWN) == NET_DF_RMC_ADAPTER_OWN) {
  494.     printf("DEC FDDI: Last transmit buffer owned by adapter.\n");
  495.     return (FAILURE);
  496.     }
  497.     /*
  498.      * Set up the header.
  499.      */
  500.     descPtr = statePtr->rmcXmtNextDescPtr;
  501.     descBufPtr = (unsigned char *)RmcXmtBufFromDesc(statePtr, descPtr);
  502.     fddiHdrPtr->prh[0] = NET_DF_PRH0;
  503.     fddiHdrPtr->prh[1] = NET_DF_PRH1;
  504.     fddiHdrPtr->prh[2] = NET_DF_PRH2;
  505.     NET_FDDI_ADDR_COPY(statePtr->fddiAddress, fddiHdrPtr->source);
  506.     NetDFBcopy(fddiHdrPtr, descBufPtr, sizeof(Net_FDDIHdr));
  507.     descBufPtr += sizeof(Net_FDDIHdr);
  508.  
  509.     /*
  510.      * Transfer the scatter/gather array to the RMC XMT ring.
  511.      */
  512.     descPtr->rmcXmtDesc = NET_DF_RMC_XMT_FIRST_PAGE | totalLength;
  513.     remaining = NET_DF_RMC_XMT_BUF_SIZE - sizeof(Net_FDDIHdr);
  514.  
  515.     for (bufCount = 0; bufCount < scatterGatherLength; 
  516.      bufCount++, scatterGatherPtr++ ) {
  517.     /*
  518.      * If it is an empty buffer then skip it.
  519.      */
  520.     length = scatterGatherPtr->length;
  521.     if (length == 0) {
  522.         continue;
  523.     }
  524.     bufPtr = scatterGatherPtr->bufAddr;
  525.     
  526.     /*
  527.      * When the while loop exits, the current RMC XMT buffer will have
  528.      * enough space left in it to place what is left of the scatter 
  529.      * gather array.
  530.      */
  531.     while (length > remaining) {
  532.         /*
  533.          * Top off the current RMC XMT buffer.
  534.          */
  535.         if (remaining > 0) {
  536.         NetDFBcopy(bufPtr, descBufPtr, remaining);
  537.         bufPtr += remaining;
  538.         length -= remaining;
  539.         }
  540.         /*
  541.          * Obtain and initialize the next RMC XMT buffer.
  542.          */
  543.         descPtr = NEXT_RMC_SEND(descPtr);
  544.         if ((descPtr->own & NET_DF_RMC_OWN) == 
  545.         NET_DF_RMC_ADAPTER_OWN) {
  546.         printf("DEC FDDI: Transmit buffer owned by adapter.\n");
  547.         return (FAILURE);
  548.         }
  549.         descPtr->rmcXmtDesc = NET_DF_RMC_XMT_MIDDLE_PAGE;
  550.         descBufPtr = (unsigned char *)RmcXmtBufFromDesc(statePtr, descPtr);
  551.         remaining = NET_DF_RMC_XMT_BUF_SIZE;
  552.     }
  553.     /*
  554.      * length <= remaining
  555.      */
  556.     NetDFBcopy(bufPtr, descBufPtr, length);
  557.     remaining -= length;
  558.     descBufPtr += length;
  559.     /*
  560.      * We've used up the current scatter gather.  Get the next.
  561.      * If remaining == 0, then the above while loop will initialize
  562.      * another RMC XMT buffer and descriptor
  563.      */
  564.     }
  565.     /*
  566.      * Upon exit of the for-loop, descPtr points to the last RMC XMT
  567.      * buffer used.  Change the descriptor to be an EOP descriptor.
  568.      */
  569.     descPtr->rmcXmtDesc |= NET_DF_RMC_XMT_LAST_PAGE;
  570.     CastOffPacket(statePtr, statePtr->rmcXmtNextDescPtr, descPtr);
  571.     MAKE_NOTE("finished casting off HOST packet.");
  572.     return(SUCCESS);
  573. }
  574.  
  575. /*
  576.  *----------------------------------------------------------------------
  577.  *
  578.  * NetDFXmitDone --
  579.  *
  580.  *    This routine will process a completed transmit command.  It will
  581.  *    check for errors and update the transmission ring pointers.
  582.  *
  583.  * Results:
  584.  *    FAILURE if problem is found.
  585.  *
  586.  * Side effects:
  587.  *    None.
  588.  *
  589.  *----------------------------------------------------------------------
  590.  */
  591. ReturnStatus
  592. NetDFXmitDone(statePtr)
  593.     register NetDFState                *statePtr; /* State of the interface */
  594. {
  595.     register volatile NetDFRmcXmtDesc   *descPtr;
  596.     register NetDFXmtElement              *xmitElementPtr;
  597.     register Net_FDDIStats              *stats;
  598.     register int                        size;
  599.     ReturnStatus            status;
  600.  
  601.     descPtr = statePtr->rmcXmtNextDescPtr;
  602.     stats = &statePtr->stats;
  603.  
  604.     /*
  605.      * If there is nothing that is currently being sent then something is
  606.      * wrong.
  607.      */
  608.     if ((statePtr->hostTransmit == TRUE) && 
  609.     (statePtr->curScatGathPtr == (Net_ScatterGather *) NIL)) {
  610.     printf( "DEC FDDI: NetDFXmitDone: No current packet\n.");
  611.     status = FAILURE;
  612.     goto exit;
  613.     }
  614.  
  615.     /*
  616.      * Check for errors.
  617.      */
  618.     if ((descPtr->own & NET_DF_RMC_OWN) == NET_DF_RMC_ADAPTER_OWN) {
  619.     printf("DEC FDDI: Bogus XMT interrupt. Buffer owned by adapter.\n");
  620.     status = FAILURE;
  621.     goto exit;
  622.     }
  623.     if (!(descPtr->rmcXmtDesc & NET_DF_RMC_XMT_SOP)) {
  624.     printf("DEC FDDI: Bogus XMT interrupt. Buffer not start of packet\n");
  625.     status = FAILURE;
  626.     goto exit;
  627.     }
  628.     if ((descPtr->rmcXmtDesc & NET_DF_RMC_XMT_DCC) != NET_DF_DCC_SUCCESS) {
  629.     printf("DEC FDDI: Unsuccessful completion code: 0x%x",
  630.            descPtr->rmcXmtDesc & NET_DF_RMC_XMT_DCC);
  631.     return (FAILURE);
  632.     }
  633.  
  634.     /*
  635.      * Traverse the packet.
  636.      */
  637.     while (TRUE) {
  638.     if (descPtr->rmcXmtDesc & NET_DF_RMC_XMT_EOP) {
  639.         break;
  640.     }
  641.     descPtr = NEXT_RMC_SEND(descPtr);
  642.     if (descPtr == statePtr->rmcXmtNextDescPtr) {
  643.         panic("DEC FDDI: Transmit ring with no end of packet.\n");
  644.     }
  645.     if ((descPtr->rmcXmtDesc & NET_DF_RMC_OWN) ==
  646.         NET_DF_RMC_ADAPTER_OWN) {
  647.         printf("DEC FDDI: XMT done: buffer owned by adapter.\n");
  648.         status = FAILURE;
  649.         goto exit;
  650.     }
  651.     }
  652.     /*
  653.      * Collect some stats.
  654.      */
  655.     stats->packetsSent++;
  656.     size = statePtr->rmcXmtNextDescPtr->rmcXmtDesc & NET_DF_RMC_XMT_PBC;
  657.     stats->bytesSent += size;
  658.     stats->transmitHistogram[size >> NET_FDDI_STATS_HISTO_SHIFT]++;
  659.  
  660.     /*
  661.      * Update the ring pointer to point at the next buffer to use.
  662.      */
  663.     statePtr->rmcXmtNextDescPtr = NEXT_RMC_SEND(descPtr);
  664.  
  665.     if (statePtr->hostTransmit == TRUE) {
  666.     /*
  667.      * Mark the packet as done.
  668.      */
  669.     MAKE_NOTE("finished transmitting HOST packet.");
  670.     statePtr->curScatGathPtr->done = TRUE;
  671.     if (statePtr->curScatGathPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  672.         MAKE_NOTE("waking up process waiting for transmit to finish.");
  673.         NetOutputWakeup(statePtr->curScatGathPtr->mutexPtr);
  674.     }
  675.     } else {
  676.     MAKE_NOTE("finished transmitting SMT packet.");
  677.     }
  678.     /*
  679.      * If there are more packets to send then send the first one on
  680.      * the queue.  Otherwise there is nothing being transmitted.
  681.      */
  682.     status = SUCCESS;
  683.     if (statePtr->resetPending == TRUE) {
  684.     goto exit;
  685.     }
  686.     
  687.     if (!List_IsEmpty(statePtr->xmitList)) {
  688.     xmitElementPtr = (NetDFXmtElement *) List_First(statePtr->xmitList);
  689.     status = OutputXmtElement(statePtr, xmitElementPtr);
  690.     } else {
  691.     statePtr->transmitting = FALSE;
  692.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  693.     }
  694. exit:
  695.     /*
  696.      * This assumes that whatever calls us will reset the chip if we return
  697.      * anything other than SUCCESS.  This way we avoid resetting the chip 
  698.      * twice in a row.
  699.      */
  700.     if ((statePtr->resetPending == TRUE) && (status == SUCCESS)) {
  701.     statePtr->transmitting = FALSE;
  702.     NetDFRestart(statePtr->interPtr);
  703.     }
  704.     if (status != SUCCESS) {
  705.     statePtr->transmitting = FALSE;
  706.     }
  707.     return status;
  708. }
  709.  
  710. /*
  711.  *----------------------------------------------------------------------
  712.  *
  713.  * NetDFOutput --
  714.  *
  715.  *    Output a packet.  The procedure is to either put the packet onto the 
  716.  *    queue of outgoing packets if packets are already being sent, or 
  717.  *    otherwise to send the packet directly.
  718.  *
  719.  * Results:
  720.  *    SUCCESS if the packet was sent or queued successfully, otherwise
  721.  *    FAILURE.
  722.  *
  723.  * Side effects:
  724.  *    Queue of packets modified.
  725.  *
  726.  *----------------------------------------------------------------------
  727.  */
  728. /*ARGSUSED*/
  729. ReturnStatus
  730. NetDFOutput(interPtr, hdrPtr, scatGathPtr, scatGathLength, rpc, statusPtr)
  731.     Net_Interface           *interPtr;      /* The network interface. */
  732.     Address               hdrPtr;           /* Packet header. */
  733.     register Net_ScatterGather *scatGathPtr;   /* Data portion of packet. */
  734.     register int               scatGathLength; /* Length of data portion 
  735.                         * gather array. */
  736.     Boolean               rpc;           /* An RPC packet? */
  737.     ReturnStatus           *statusPtr;     /* Status from sending
  738.                         * packet.*/
  739. {
  740.     register NetDFState            *statePtr;
  741.     register NetDFXmtElement        *xmitPtr;
  742.     Net_FDDIHdr                    *fddiHdrPtr = (Net_FDDIHdr *)hdrPtr;
  743.     Boolean                restart = FALSE;
  744.     ReturnStatus            status;
  745.  
  746.     statePtr = (NetDFState *) interPtr->interfaceData;
  747.  
  748.     MASTER_LOCK(&interPtr->mutex);
  749.  
  750.     if (statePtr->flags & NET_DF_FLAGS_RESETTING) {
  751.     MAKE_NOTE("Process waiting in NetDFOutput while resetting.\n");
  752.     do {
  753.         Sync_MasterWait(&statePtr->doingReset, &interPtr->mutex, FALSE);
  754.     } while (statePtr->flags & NET_DF_FLAGS_RESETTING);
  755.     }
  756.  
  757.     /*
  758.      * See if the packet is for us.  In this case just copy in the packet
  759.      * and call the higher level routine.
  760.      */
  761.     if (!Net_FDDIAddrCmp(statePtr->fddiAddress, fddiHdrPtr->dest)) {
  762.     int i, length;
  763.  
  764.         length = sizeof(Net_FDDIHdr);
  765.         for (i = 0; i < scatGathLength; i++) {
  766.             length += scatGathPtr[i].length;
  767.         }
  768.         if (length <= NET_DF_MAX_PACKET_SIZE) {
  769.         register Address bufPtr;
  770.  
  771.         MAKE_NOTE("--- Loopback buffer used ---");
  772.  
  773.         NET_FDDI_ADDR_COPY(statePtr->fddiAddress, fddiHdrPtr->source);
  774.  
  775.         bufPtr = (Address)statePtr->loopBackBuffer;
  776.         bcopy((Address)fddiHdrPtr, bufPtr, sizeof(Net_FDDIHdr));
  777.         bufPtr += sizeof(Net_FDDIHdr);
  778.             Net_GatherCopy(scatGathPtr, scatGathLength, bufPtr);
  779.  
  780.         Net_Input(interPtr, (Address)statePtr->loopBackBuffer, length);
  781.         }
  782.  
  783.         scatGathPtr->done = TRUE;
  784.  
  785.     status = SUCCESS;
  786.     if (statusPtr != (ReturnStatus *) NIL) {
  787.         *statusPtr = SUCCESS;
  788.     } 
  789.     goto exit;
  790.     }
  791.  
  792.     /*
  793.      * If no packet is being sent then go ahead and send this one.
  794.      */
  795.     if (!statePtr->transmitting) {
  796.     status = OutputPacket(fddiHdrPtr, scatGathPtr, 
  797.                   scatGathLength, statePtr);
  798.     if (status != SUCCESS) {
  799.         restart = TRUE;
  800.     } else if (statusPtr != (ReturnStatus *) NIL) {
  801.         *statusPtr = SUCCESS;
  802.     } 
  803.     goto exit;
  804.     }
  805.  
  806.     /*
  807.      * There is a packet being sent so this packet has to be put onto the
  808.      * transmission queue.  Get an element off of the transmission free list.  
  809.      * If none available then drop the packet.
  810.      */
  811.     if (List_IsEmpty(statePtr->xmitFreeList)) {
  812.     statePtr->stats.xmtPacketsDropped++;
  813.         scatGathPtr->done = TRUE;
  814.     status = FAILURE;
  815.     goto exit;
  816.     }
  817.  
  818.     xmitPtr = (NetDFXmtElement *) 
  819.     List_First((List_Links *) statePtr->xmitFreeList);
  820.     List_Remove((List_Links *) xmitPtr);
  821.  
  822.     /*
  823.      * Initialize the list element and place on the queue.
  824.      */
  825.     xmitPtr->fddiHdrPtr = fddiHdrPtr;
  826.     xmitPtr->scatterGatherPtr = scatGathPtr;
  827.     xmitPtr->scatterGatherLength = scatGathLength;
  828.     xmitPtr->xmtType = NET_DF_XMT_HOST;
  829.     List_Insert((List_Links *) xmitPtr, LIST_ATREAR(statePtr->xmitList)); 
  830.  
  831.     if (statusPtr != (ReturnStatus *) NIL) {
  832.     *statusPtr = SUCCESS;
  833.     } 
  834.     status = SUCCESS;
  835. exit:
  836.     MASTER_UNLOCK(&interPtr->mutex);
  837.     if (restart) {
  838.     Net_DFRestart(interPtr);
  839.     }
  840.     return status;
  841. }
  842.  
  843. /*
  844.  *----------------------------------------------------------------------
  845.  *
  846.  * NetDFSmtOutput --
  847.  *
  848.  *    Transfer a packet from the SMT XMT ring to the RMC XMT ring.
  849.  *      If a packet is currently being sent, then the SMT packet is
  850.  *      placed on the transmit queue;  otherwise, it is sent directly.
  851.  *
  852.  * Results:
  853.  *    SUCCESS if the packet was sent or queued successfully, FAILURE
  854.  *    otherwise.
  855.  *
  856.  * Side effects:
  857.  *    Queue of packets modified.
  858.  *
  859.  *----------------------------------------------------------------------
  860.  */
  861. ReturnStatus
  862. NetDFSmtOutput(interPtr)
  863.     Net_Interface *interPtr;
  864. {
  865.     register NetDFState      *statePtr;
  866.     register NetDFXmtElement *xmitPtr;
  867.     ReturnStatus         status;
  868.     Boolean             restart = FALSE;
  869.  
  870.     statePtr = (NetDFState *)interPtr->interfaceData;
  871.  
  872.     /*
  873.      * If no packet is being sent then go ahead and send this one.
  874.      */
  875.     if (!statePtr->transmitting) {
  876.     status = NetDFOutputSmtPacket(statePtr, statePtr->smtXmtNextDescPtr);
  877.     if (status != SUCCESS) {
  878.         restart = TRUE;
  879.     }
  880.     goto exit;
  881.     }
  882.     /*
  883.      * There is a packet being sent so this packet has to be put onto the
  884.      * transmission queue.  Get an element off of the transmission free list.  
  885.      * If none available then drop the packet.
  886.      */
  887.     if (List_IsEmpty(statePtr->xmitFreeList)) {
  888.     statePtr->stats.xmtPacketsDropped++;
  889.     status = FAILURE;
  890.     goto exit;
  891.     }
  892.  
  893.     xmitPtr = (NetDFXmtElement *) 
  894.     List_First((List_Links *) statePtr->xmitFreeList);
  895.     List_Remove((List_Links *) xmitPtr);
  896.  
  897.     /*
  898.      * Initialize the list element.
  899.      */
  900.     xmitPtr->fddiHdrPtr = NULL;
  901.     xmitPtr->scatterGatherPtr = NULL;
  902.     xmitPtr->scatterGatherLength = 0;
  903.     xmitPtr->smtDescPtr = statePtr->smtXmtNextDescPtr;
  904.     xmitPtr->xmtType = NET_DF_XMT_SMT;
  905.  
  906.     statePtr->smtXmtNextDescPtr = NEXT_SMT_SEND(statePtr->smtXmtNextDescPtr);
  907.     /* 
  908.      * Put onto the transmission queue.
  909.      */
  910.     List_Insert((List_Links *) xmitPtr, LIST_ATREAR(statePtr->xmitList)); 
  911.     status = SUCCESS;
  912. exit:
  913.     if (restart) {
  914.     NetDFRestart(interPtr);
  915.     }
  916.     return SUCCESS;
  917. }
  918.  
  919. /*
  920.  *----------------------------------------------------------------------
  921.  *
  922.  * NetDFXmitDrop --
  923.  *
  924.  *    Drop the current packet.  Called at the beginning of the
  925.  *    restart sequence, before curScatGathPtr is reset to NIL.
  926.  *
  927.  * Results:
  928.  *    None.
  929.  *
  930.  * Side effects:
  931.  *    Current scatter gather pointer is reset and processes waiting
  932.  *    for synchronous output are notified.
  933.  *
  934.  *----------------------------------------------------------------------
  935.  */
  936. void
  937. NetDFXmitDrop(statePtr)
  938.     register NetDFState *statePtr;     /* State of the interface. */
  939. {
  940.     MAKE_NOTE("Dropping current packet.");
  941.     if (statePtr->curScatGathPtr != (Net_ScatterGather *) NIL) {
  942.     statePtr->curScatGathPtr->done = TRUE;
  943.     if (statePtr->curScatGathPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  944.         NetOutputWakeup(statePtr->curScatGathPtr->mutexPtr);
  945.     }
  946.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  947.     }
  948.     statePtr->transmitting = FALSE;
  949.     return;
  950. }
  951.  
  952. /*
  953.  *----------------------------------------------------------------------
  954.  *
  955.  * NetDFXmitRestart --
  956.  *
  957.  *    Restart transmission of packets at the end of the restart
  958.  *    sequence, after a chip reset.
  959.  *
  960.  * Results:
  961.  *    None.
  962.  *
  963.  * Side effects:
  964.  *    Output queue started up.
  965.  *
  966.  *----------------------------------------------------------------------
  967.  */
  968. void
  969. NetDFXmitRestart(statePtr)
  970.     register NetDFState        *statePtr;     /* State of the interface. */
  971. {
  972.     register NetDFXmtElement    *xmitElementPtr;
  973.     ReturnStatus            status;
  974.  
  975.     /*
  976.      * Start output if there are any packets queued up.
  977.      */
  978.     if (!List_IsEmpty(statePtr->xmitList)) {
  979.     xmitElementPtr = (NetDFXmtElement *) List_First(statePtr->xmitList);
  980.     status = OutputXmtElement(statePtr, xmitElementPtr);
  981.     List_Move((List_Links *) xmitElementPtr, 
  982.           LIST_ATREAR(statePtr->xmitFreeList));
  983.     /*
  984.      * If we cannot successfully output the packet, then flush the
  985.      * transmit queue.
  986.      */
  987.     if (status != SUCCESS) {
  988.         printf("DEC FDDI: Cannot output first packet on restart.\n");
  989.         NetDFXmitFlushQ(statePtr);
  990.     }
  991.     } else {
  992.     statePtr->transmitting = FALSE;
  993.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  994.     }
  995.     return;
  996. }
  997.  
  998. /*
  999.  *----------------------------------------------------------------------
  1000.  *
  1001.  * NetDFXmitFlushQ --
  1002.  *
  1003.  *    Drop all packets in the transmit queue.
  1004.  *
  1005.  * Results:
  1006.  *    None.
  1007.  *
  1008.  * Side effects:
  1009.  *    Processes waiting for synchronous output are notified.
  1010.  *
  1011.  *----------------------------------------------------------------------
  1012.  */
  1013. void
  1014. NetDFXmitFlushQ(statePtr)
  1015.     register NetDFState      *statePtr;    /* State of the interface. */
  1016. {
  1017.     register NetDFXmtElement *xmtElementPtr;
  1018.  
  1019.     while (TRUE) {
  1020.     if (List_IsEmpty(statePtr->xmitList)) {
  1021.         break;
  1022.     }
  1023.     xmtElementPtr = (NetDFXmtElement *) List_First(statePtr->xmitList);
  1024.     switch(xmtElementPtr->xmtType) {
  1025.     case NET_DF_XMT_HOST:
  1026.         xmtElementPtr->scatterGatherPtr->done = TRUE;
  1027.         if (xmtElementPtr->scatterGatherPtr->mutexPtr != 
  1028.         (Sync_Semaphore *) NIL) {
  1029.         NetOutputWakeup(xmtElementPtr->scatterGatherPtr->mutexPtr);
  1030.         }
  1031.         break;
  1032.     case NET_DF_XMT_SMT:
  1033.     default:
  1034.         break;
  1035.     }
  1036.     List_Move((List_Links *) xmtElementPtr, 
  1037.           LIST_ATREAR(statePtr->xmitFreeList));
  1038.     }
  1039. }
  1040.  
  1041.